package com.ayf.payment.game.api.service;

import com.alibaba.fastjson.JSON;
import com.ayf.payment.game.api.dto.Token;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class TokenRepository {

    public static final long ACCESS_TOKEN_EXPIRED_SECOND = 60L * 60 * 8;

    public static final long ACCESS_TOKEN_CLIENT_EXPIRED_SECOND = 60L * 60 * 4;

    @Autowired
    private StringRedisTemplate redisTemplate;

    public boolean save(Token entity) {
        try {
            if(entity.getLoginType().equals("gateWay")){
                redisTemplate.boundValueOps(genAccessTokenKey(entity.getLoginType()+"-"+entity.getAccessToken()))
                        .set(entity.getRefreshToken(), entity.getExpiredSeconds(), TimeUnit.SECONDS);
                redisTemplate.boundValueOps(genRefreshToken(entity.getRefreshToken()))
                        .set(JSON.toJSONString(entity), entity.getExpiredSeconds(), TimeUnit.SECONDS);

            }else {
                redisTemplate.boundValueOps(genAccessTokenKey(entity.getAccessToken()))
                        .set(entity.getRefreshToken(), entity.getExpiredSeconds(), TimeUnit.SECONDS);

                String accessTokenStr = redisTemplate.boundValueOps(genMemberIdAndAppIdKey(entity.getMerchantId())).get();
                if (StringUtils.isNotBlank(accessTokenStr)) {
                    //只存50个token 1649
                    if (accessTokenStr.length() >= 1649) {
                        String temp = accessTokenStr;
                        String deToken = temp.substring(0, 32);
                        deleteTokenByToken(deToken);
                        accessTokenStr = accessTokenStr.substring(33);
                    }
                    accessTokenStr = accessTokenStr + ";" + entity.getAccessToken();
                } else {
                    accessTokenStr = entity.getAccessToken();
                }

                redisTemplate.boundValueOps(genMemberIdAndAppIdKey(entity.getMerchantId()))
                        .set(accessTokenStr, entity.getExpiredSeconds(), TimeUnit.SECONDS);

                redisTemplate.boundValueOps(genRefreshToken(entity.getRefreshToken()))
                        .set(JSON.toJSONString(entity), entity.getExpiredSeconds(), TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            LogPortal.error("redis连接失败, token信息[{}]", e, entity.toString());
            LogPortal.error("REDIS_ERROR: redis连接失败, token信息[{}]", entity.toString());
            return false;
        }
    }

    public void deleteTokenByToken(String token) {
        if (StringUtils.isBlank(token)) {
            return;
        }
        try {
            deleteRedisByToken(token);
        }catch (Exception e){
            LogPortal.error("redis删除key发生{}异常，异常信息为：{}", e, e.getClass().getSimpleName(), e.getMessage());
        }
    }

    private void deleteRedisByToken(String accessToken) {
        if (StringUtils.isBlank(accessToken)) {
            return;
        }
        String refreshToken = redisTemplate.boundValueOps(genAccessTokenKey(accessToken)).get();
        deleteRefreshToken(refreshToken);
    }

    public void deleteRefreshToken(String refreshToken) {
        if (StringUtils.isBlank(refreshToken)) {
            return;
        }
        Token entity = getTokenByRefreshToken(refreshToken);
        if (entity == null) {
            return;
        }
        List<String> list = new ArrayList<String>(2);
        list.add(genAccessTokenKey(entity.getAccessToken()));
        list.add(genRefreshToken(entity.getRefreshToken()));
        redisTemplate.delete(list);
        String accessTokenStr= redisTemplate.boundValueOps(genMemberIdAndAppIdKey(entity.getMerchantId())).get();
        if (StringUtils.isEmpty(accessTokenStr)) {
            return;
        }
        redisTemplate.boundValueOps(genMemberIdAndAppIdKey(entity.getMerchantId()))
                .set(accessTokenStr.replaceAll(entity.getAccessToken() + ";", "").replaceAll(";" + entity.getAccessToken(), ""), entity.getExpiredSeconds(), TimeUnit.SECONDS);
    }

    public void delete(Integer memberId) {
        String key = genMemberIdAndAppIdKey(memberId);
        try {
            String accessToken = redisTemplate.boundValueOps(key).get();
            if (StringUtils.isNotBlank(accessToken)) {
                String[] split = accessToken.split(";");
                for (String s : split) {
                    if (StringUtils.isEmpty(s)) {
                        continue;
                    }
                    deleteRedisByToken(s);
                }
            }
        } catch (Exception e) {
            LogPortal.error("redis删除key发生{}异常，异常信息为：{}", e, e.getClass().getSimpleName(), e.getMessage());
        }
    }
    public void deleteTokenByLoginId(Integer merchantId, Integer loginId) {
        if ( merchantId == null||loginId==null) {
            return;
        }
        String key = genMemberIdAndAppIdKey(merchantId);
        try {
            String accessToken = redisTemplate.boundValueOps(key).get();
            if (StringUtils.isNotBlank(accessToken)) {
                String[] split = accessToken.split(";");
                for (String s : split) {
                    if (StringUtils.isEmpty(s)) {
                        continue;
                    }
                    Token token = getTokenByAccessToken(s);
                    if (token != null && loginId.equals(token.getLoginId())) {
                        deleteRedisByToken(s);
                    }
                }
            }
        }catch (Exception e){
            LogPortal.error("redis删除key发生{}异常，异常信息为：{}", e, e.getClass().getSimpleName(), e.getMessage());
        }
    }

    public Token getTokenByAccessToken(String accessToken) {
        if (StringUtils.isBlank(accessToken)) {
            return null;
        }
        try {
            String refreshToken = redisTemplate.boundValueOps(genAccessTokenKey(accessToken)).get();
            return getTokenByRefreshToken(refreshToken);
        } catch (Exception e) {
            LogPortal.error("redis连接失败, accessToken[{}]", e, accessToken);
            LogPortal.error("REDIS_ERROR: redis连接失败, accessToken[{}]", accessToken);
            return null;
        }
    }


    public Token getTokenByRefreshToken(String refreshToken) {
        if (StringUtils.isBlank(refreshToken)) {
            return null;
        }
        String json = redisTemplate.boundValueOps(genRefreshToken(refreshToken)).get();
        if (StringUtils.isBlank(json)) {
            return null;
        }
        return JSON.parseObject(json, Token.class);
    }

    private static String genMemberIdAndAppIdKey(Integer memberId) {
        return new StringBuilder().append("token-memberid-").append(memberId).toString();
    }

    private static String genMemberIdAndAppIdKey(String memberId) {
        return new StringBuilder().append("token-memberid-").append(memberId).toString();
    }

    private static String genAccessTokenKey(String accessToken) {
        return new StringBuilder().append("token-accesstoken-").append(accessToken).toString();
    }

    private static String genRefreshToken(String refreshToken) {
        return new StringBuilder().append("token-refreshtoken-").append(refreshToken).toString();
    }
}
